﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Interop;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Converters;
using System.Windows.Media.Composition;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Shapes;
using System.Xml;
using System.Runtime.InteropServices;
using GadgetBase;

namespace WeatherGadget
{
    public class WeatherGadget : GadgetWindow
    {
        private string folder;

        //@"C:\weather_data_v2.xml";
        const string url = @"http://vwidget.accuweather.com/widget/vista2/weather_data_v2.asp?location=EUR|BY|BO000|MINSK|&metric=1";

        private struct DayData
        {
            public struct DayTimeData
            {
                public string daytimeTextShort;
                public string daytimeTextLong;
                public string daytimeIcon;
                public string daytimeHigh;
                public string daytimeRealFeelHigh;
                public string daytimeWindSpeed;
                public string daytimeWindDirection;
                public string daytimeWindGust;
                public string daytimeMaxUV;
                public string daytimeRain;
                public string daytimeSnow;
                public string daytimePrecip;
            }

            public struct NightTimeData
            {
                public string nighttimeTextShort;
                public string nighttimeTextLong;
                public string nighttimeIcon;
                public string nighttimeLow;
                public string nighttimeRealFeelLow;
                public string nighttimeWindSpeed;
                public string nighttimeWindDirection;
                public string nighttimeWindGust;
                public string nighttimeRain;
                public string nighttimeSnow;
                public string nighttimePrecip;
            }


            public DayTimeData DayTime;
            public NightTimeData NightTime;

            private static DayTimeData DayTimeFromXmlNode(XmlNode day, XmlNamespaceManager nsmgr)
            {
                DayTimeData result = new DayTimeData();

                XmlNode daytime = day.SelectSingleNode("./w:daytime", nsmgr);
                result.daytimeTextShort = daytime["txtshort"].InnerText;
                result.daytimeTextLong = daytime["txtlong"].InnerText;
                result.daytimeIcon = daytime["wxf"].Attributes["icon"].Value;
                result.daytimeHigh = daytime["wxf"].Attributes["htmp"].Value;
                result.daytimeRealFeelHigh = daytime["wxf"].Attributes["rfh"].Value;
                result.daytimeWindSpeed = daytime["wxf"].Attributes["wspd"].Value;
                result.daytimeWindDirection = daytime["wxf"].Attributes["wdir"].Value;
                result.daytimeWindGust = daytime["wxf"].Attributes["wgus"].Value;
                result.daytimeMaxUV = daytime["wxf"].Attributes["mxuv"].Value;
                result.daytimeRain = daytime["wxf"].Attributes["rain"].Value;
                result.daytimeSnow = daytime["wxf"].Attributes["snow"].Value;
                result.daytimePrecip = daytime["wxf"].Attributes["prec"].Value;

                return result;
            }

            private static NightTimeData NightTimeFromXmlNode(XmlNode day, XmlNamespaceManager nsmgr)
            {
                NightTimeData result = new NightTimeData();
                XmlNode nighttime = day.SelectSingleNode("./w:nighttime", nsmgr);
                result.nighttimeTextShort = nighttime["txtshort"].InnerText;
                result.nighttimeTextLong = nighttime["txtlong"].InnerText;
                result.nighttimeIcon = nighttime["wxf"].Attributes["icon"].Value;
                result.nighttimeLow = nighttime["wxf"].Attributes["ltmp"].Value;
                result.nighttimeRealFeelLow = nighttime["wxf"].Attributes["rfl"].Value;
                result.nighttimeWindSpeed = nighttime["wxf"].Attributes["wspd"].Value;
                result.nighttimeWindDirection = nighttime["wxf"].Attributes["wdir"].Value;
                result.nighttimeWindGust = nighttime["wxf"].Attributes["wgus"].Value;
                result.nighttimeRain = nighttime["wxf"].Attributes["rain"].Value;
                result.nighttimeSnow = nighttime["wxf"].Attributes["snow"].Value;
                result.nighttimePrecip = nighttime["wxf"].Attributes["prec"].Value;

                return result;
            }

            private static DayData FromXmlNode(XmlNode day, XmlNamespaceManager nsmgr)
            {
                DayData data = new DayData();

                //Daytime forecast data               
                data.DayTime = DayTimeFromXmlNode(day, nsmgr);

                //Nighttime forecast data
                data.NightTime = NightTimeFromXmlNode(day, nsmgr);

                return data;
            }

            public static DayData[] FromXmlDocument(XmlDocument document)
            {
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
                nsmgr.AddNamespace("w", document.DocumentElement.NamespaceURI);
                XmlNodeList days = document.SelectNodes("//w:forecast/w:day", nsmgr);

                List<DayData> list = new List<DayData>();
                foreach (XmlNode day in days)
                {
                    DayData data = FromXmlNode(day, nsmgr);

                    list.Add(data);
                }

                return list.ToArray();
            }
        }


        private struct ConditionData
        {
            public string temperature;
            public string realFeel;
            public string humidity;
            public string text;
            public string icon;
            public string windGust;
            public string windSpeed;
            public string windDir;
            public string visibility;
            public string precip;
            public string uvindex;
            public string uvtext;

            public static ConditionData FromXmlDocument(XmlDocument document)
            {
                ConditionData result = new ConditionData();

                XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
                nsmgr.AddNamespace("w", document.DocumentElement.NamespaceURI);

                XmlNode daytime = document.SelectSingleNode("//w:wxc", nsmgr);
                result.temperature = daytime.Attributes["temp"].Value;
                result.realFeel = daytime.Attributes["rft"].Value;
                result.humidity = daytime.Attributes["hum"].Value;
                result.text = daytime.Attributes["text"].Value;
                result.icon = daytime.Attributes["icon"].Value;
                result.windGust = daytime.Attributes["wgus"].Value;
                result.windSpeed = daytime.Attributes["wspd"].Value;
                result.windDir = daytime.Attributes["wdir"].Value;
                result.visibility = daytime.Attributes["vis"].Value;
                result.precip = daytime.Attributes["prec"].Value;
                result.uvindex = daytime.Attributes["uvi"].Value;
                result.uvtext = daytime.Attributes["uvt"].Value;

                return result;
            }
        }

        private XmlDocument doc = new XmlDocument();
        private ConditionData data;

        private Weather weather = new Weather();
        private DispatcherTimer timer = new DispatcherTimer();

        public WeatherGadget()
            : base()
        {
            this.Title = "Weather";

            base.Width = 125 + 5;
            base.Height = 62 + 5;

            this.folder = GlobalMethods.GetFullPath(@"images\");
            
            base.Children.Add(this.weather);            
                        
            RefreshWeather();

            this.timer.Interval = new TimeSpan(0, 0, 30, 0, 0);
            this.timer.Tick += new EventHandler(this.timer_Tick);
            this.timer.IsEnabled = true;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            RefreshWeather();
        }

        private void RefreshWeather()
        {
            doc.Load(url);
            this.data = ConditionData.FromXmlDocument(doc);

            this.weather.SetTemperature(this.data.temperature + "°C");

            string imagePath = this.folder + "icons/sm/" + this.data.icon + ".png";
            this.weather.SetWeatherStateImage(GlobalMethods.GetBitmapImage(imagePath));
            
        }        


        private class Weather : GadgetBase.Gadgets.Gadget
        {
            private string folder;

            private const string backgroundImageName = "BLUEDOCKED-base.png";
            private const string highlight1ImageName = "BLUEDOCKED-highlight-01.png";
            private const string highlight2ImageName = "BLUEDOCKED-highlight-02.png";

            private Label temperatureLabel = new Label();
            private Image weatherStateImage = new Image();

            public Weather()
            {
                this.folder = GlobalMethods.GetFullPath(@"images\");

                base.Background = new SolidColorBrush(Color.FromArgb(20, 0, 0, 0));
                SetBackground(folder + backgroundImageName);

                //this.weatherStateImage.HorizontalAlignment = HorizontalAlignment.Right;
                //this.weatherStateImage.VerticalAlignment = VerticalAlignment.Top;
                this.weatherStateImage.Stretch = Stretch.UniformToFill;
                this.weatherStateImage.Margin = new Thickness(70, 7, 0, 0);                
                base.Children.Add(this.weatherStateImage);

                this.temperatureLabel.Foreground = Brushes.White;
                this.temperatureLabel.FontSize = 25;
                OuterGlowBitmapEffect effect = new OuterGlowBitmapEffect();
                effect.GlowColor = Colors.Black;
                effect.GlowSize = 5;
                effect.Opacity = 0.5f;
                this.temperatureLabel.BitmapEffect = effect;
                this.temperatureLabel.Margin = new Thickness(10, 11, 0, 0);
                base.Children.Add(this.temperatureLabel);                
                
                
                Image highlight1Image = new Image();
                highlight1Image.Source = GadgetBase.GlobalMethods.GetBitmapImage(this.folder + highlight1ImageName);
                //highlight1Image.Height = this.Height;
                //highlight1Image.Width = this.Width;
                highlight1Image.Stretch = Stretch.UniformToFill;
                highlight1Image.Margin = new Thickness(3, 3, 0, 0);
                highlight1Image.HorizontalAlignment = HorizontalAlignment.Left;
                highlight1Image.VerticalAlignment = VerticalAlignment.Top;
                base.Children.Add(highlight1Image);
                

                Image highlight2Image = new Image();
                highlight2Image.Source = GadgetBase.GlobalMethods.GetBitmapImage(this.folder + highlight2ImageName);
                //highlight2Image.Height = this.Height;
                //highlight2Image.Width = this.Width;
                highlight2Image.Stretch = Stretch.UniformToFill;
                highlight2Image.Margin = new Thickness(3, 3, 0, 0);
                highlight2Image.HorizontalAlignment = HorizontalAlignment.Left;
                highlight2Image.VerticalAlignment = VerticalAlignment.Top;
                base.Children.Add(highlight2Image);
            }

            public void SetTemperature(object temperature)
            {
                this.temperatureLabel.Content = temperature;
            }

            public void SetWeatherStateImage(ImageSource image)
            {
                this.weatherStateImage.Source = image;
                this.weatherStateImage.Height = image.Height;
                this.weatherStateImage.Width = image.Width;
            }
        }
    }
}
